home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume20 / reactivekbd / part01 next >
Encoding:
Internet Message Format  |  1989-10-16  |  48.4 KB

  1. Subject:  v20i029:  Command-line editor with predictions, Part01/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Mark James <cpsc.UCalgary.CA!jamesm>
  7. Posting-number: Volume 20, Issue 29
  8. Archive-name: reactivekbd/part01
  9.  
  10. [  This is one of the wildest concepts I've seen; not unlike DWIM in
  11.    the Interlisp world, I guess.  It uses pty's and BSD-style ioctl's.
  12.    The package also has the FSF getopt(3) bundled in.  /r$  ]
  13.  
  14. The Reactive Keyboard is a general purpose command line editor with the
  15. addition of predictive text generation.  It interfaces with a standard
  16. shell and allows simple editing of input lines.  It will also predict new
  17. input lines based on previous input.  Typing "make" will create the
  18. program in the current directory.
  19.  
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then unpack
  23. # it by saving it into a file and typing "sh file".  To overwrite existing
  24. # files, type "sh file -c".  You can also feed this as standard input via
  25. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  26. # will see the following message at the end:
  27. #        "End of archive 1 (of 4)."
  28. # Contents:  MANIFEST Makefile README command_line.c dt_complete.c
  29. #   file+rk.h freq.c functions.h myabspath.c myabspath.h rk_button.c
  30. #   rk_button.h rk_file.c
  31. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  32. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  34. else
  35. echo shar: Extracting \"'MANIFEST'\" \(654 characters\)
  36. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  37. X   File Name        Archive #    Description
  38. X-----------------------------------------------------------
  39. X MANIFEST                   1    
  40. X Makefile                   1    
  41. X README                     1    
  42. X command_line.c             1    
  43. X dt_complete.c              1    
  44. X file+rk.c                  3    
  45. X file+rk.h                  1    
  46. X freq.c                     1    
  47. X functions.c                4    
  48. X functions.h                1    
  49. X getopt.c                   2    
  50. X myabspath.c                1    
  51. X myabspath.h                1    
  52. X parse_keys.c               2    
  53. X rk.1                       2    
  54. X rk_button.c                1    
  55. X rk_button.h                1    
  56. X rk_file.c                  1    
  57. END_OF_FILE
  58. if test 654 -ne `wc -c <'MANIFEST'`; then
  59.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  60. fi
  61. # end of 'MANIFEST'
  62. fi
  63. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  64.   echo shar: Will not clobber existing file \"'Makefile'\"
  65. else
  66. echo shar: Extracting \"'Makefile'\" \(314+ characters\)
  67. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  68. XCFLAGS = -g
  69. X
  70. XOBJS = file+rk.o rk_file.o rk_button.o parse_keys.o getopt.o \
  71. X    dt_complete.o functions.o myabspath.o command_line.o
  72. X
  73. X.c.o:
  74. X    cc $(CFLAGS) -c $<
  75. X
  76. Xall: rk rk.man freq
  77. X
  78. Xrk: $(OBJS)
  79. X    cc $(CFLAGS) -o rk $(OBJS) -ltermcap
  80. X
  81. Xrk.man : rk.1
  82. X    tbl rk.1|nroff -man > rk.man
  83. X
  84. Xfreq: freq.c
  85. X    cc $(CFLAGS) -o freq freq.c
  86. END_OF_FILE
  87. echo 'shar: Size check ignored; edited by moderator for long lines.'
  88. #if test 314 -ne `wc -c <'Makefile'`; then
  89. #    echo shar: \"'Makefile'\" unpacked with wrong size!
  90. #fi
  91. # end of 'Makefile'
  92. fi
  93. if test -f 'README' -a "${1}" != "-c" ; then 
  94.   echo shar: Will not clobber existing file \"'README'\"
  95. else
  96. echo shar: Extracting \"'README'\" \(454 characters\)
  97. sed "s/^X//" >'README' <<'END_OF_FILE'
  98. XThe Reactive Keyboard is a general purpose command line editor with the
  99. Xaddition of predictive text generation.  It interfaces with a standard shell
  100. Xand allows simple editing of input lines.  It will also predict new input
  101. Xlines based on previous input.  Typing "make"
  102. Xwill create the program in the current directory.
  103. X
  104. XPermission is granted for any individual or institution to use, copy or
  105. Xdistribute this program so long as it is not sold for profit.
  106. END_OF_FILE
  107. if test 454 -ne `wc -c <'README'`; then
  108.     echo shar: \"'README'\" unpacked with wrong size!
  109. fi
  110. # end of 'README'
  111. fi
  112. if test -f 'command_line.c' -a "${1}" != "-c" ; then 
  113.   echo shar: Will not clobber existing file \"'command_line.c'\"
  114. else
  115. echo shar: Extracting \"'command_line.c'\" \(5852 characters\)
  116. sed "s/^X//" >'command_line.c' <<'END_OF_FILE'
  117. X#define ZERO_FREQ_FILE "/.rk.zero_freq"
  118. X#define PRIME_FILE "/.rk.log_file"
  119. X#define KEY_FILE "/.rk.keys"
  120. X
  121. X#include "file+rk.h"
  122. X#include "rk_button.h"
  123. X#include "sys/file.h"
  124. X#include <stdio.h>
  125. X
  126. Xprint_help()
  127. X{
  128. X    printf("RK command line arguments:\n");
  129. X
  130. X    printf("    -b <buffers>    The number of buffers used by rk to save previous\n");
  131. X    printf("             commands used by 'previous_line'. Default: 60.\n\n");
  132. X
  133. X    printf("    -e <length>    The maximum length of predictions at the end of the\n");
  134. X    printf("            line. Default: 40.\n\n");
  135. X
  136. X
  137. X    printf("    -f <count>    The maximum frequency count for any given context\n");
  138. X    printf("            Default: 128\n\n");
  139. X
  140. X    printf("    -i <length>    The maximum length of predictions in the middle of\n");
  141. X    printf("            the line. Default: 8.\n\n");
  142. X
  143. X    printf("    -k <keys file>    The file to read key bindings from.\n");
  144. X    printf("            Default:$HOME/.rk.keys\n\n");
  145. X
  146. X    printf("    -n <nodes>    The amount of memory to allocate initially to speed\n");
  147. X    printf("            up creation of nodes.  After this memory is used up,\n");
  148. X    printf("            more will be allocated, but this will be slower.\n");
  149. X    printf("            Default: 64*1024 nodes.\n\n");
  150. X
  151. X    printf("    -o <order>    This argument controls how deep a tree will be built\n");
  152. X    printf("            by rk inorder to make predictions.  As order\n");
  153. X    printf("            increases, the accuracy of predictions increases,\n");
  154. X    printf("            but the speed decreases. Default: 8.\n\n");
  155. X    printf("    -p <prime file>    The file used to prime the Reactive Keyboard.\n");
  156. X    printf("            Default:$HOME/.rk.log_file.\n\n");
  157. X
  158. X
  159. X    printf("    -s <startup>    The maximum number of characters to be read from the\n");
  160. X    printf("             prime file at startup. Default: 16*1024.\n\n");
  161. X
  162. X    printf("    -z <zero freq>    The zero frequency file name.\n");
  163. X    printf("            Default:$HOME/.rk.zero_freq\n\n");
  164. X
  165. X    printf("    -A    Toggle add_space_mode\n");
  166. X    printf("    -E    Toggle eol_only mode.\n");
  167. X    printf("    -L    Toggle eol_longer mode.\n");
  168. X    printf("    -N    Toggle truncate at newline mode.\n");
  169. X    printf("    -P    Toggle predictions on/off.\n");
  170. X    printf("    -S    Toggle show_eol_mode.\n");
  171. X    printf("    -g    Make this not a login shell.\n");
  172. X    printf("    -h    Print this help.\n");
  173. X    printf("    -l    Toggle lisp mode.\n");
  174. X    printf("    -m    Start up silently.\n");
  175. X    printf("    -v    Print Version.\n");
  176. X
  177. X}
  178. X
  179. Xprint_version()
  180. X{
  181. X    char            tbuf[128];
  182. X    printf("RK_Button Version:%s.\n", RK_VERSION);
  183. X}
  184. X
  185. Xextern ED_STRUCT editor_data;
  186. X
  187. X
  188. Xget_command_line_arguments(argc,argv)
  189. Xint argc;
  190. Xchar *argv[];
  191. X{
  192. X    extern int optind;
  193. X    extern char *optarg;
  194. X    int i;
  195. X
  196. X    extern num_buffers;
  197. X    extern char *zero_freq_file;
  198. X    static char z_freq_buf[256];
  199. X    extern char *prime_file;
  200. X    static char prime_buf[256];
  201. X    extern char *key_file;
  202. X    static char key_buf[256];
  203. X    extern    max_len;
  204. X    extern    max_eol;
  205. X    extern    maxk;
  206. X    extern    maxprime;
  207. X    extern  max_freq;
  208. X    extern  max_nodes;
  209. X    extern  char silent;
  210. X    extern  char login;
  211. X    extern  char pred_mode,
  212. X             pred_on_display,
  213. X             lisp_mode,
  214. X             nl_truncate_mode,
  215. X             eol_only_mode,
  216. X             eol_longer_mode,
  217. X                 add_space_mode,
  218. X             show_eol_mode;
  219. X    
  220. X    zero_freq_file=prime_file=key_file=NULL;
  221. X
  222. X    while ((i = getopt(argc, argv,"b:e:f:i:k:n:o:p:s:z:AELNPSghlmv")) 
  223. X                != EOF) {
  224. X        switch( i ) {
  225. X        case 'b': num_buffers=atoi(optarg)+1;
  226. X            if(num_buffers<1)
  227. X                abortit("-b:Buffers must be larger than 1.\n",-1);
  228. X            break;
  229. X            /* 1.. MAXINT*/
  230. X        case 'e': max_eol=atoi(optarg);
  231. X            if((max_eol<1)||(max_eol>132))
  232. X                abortit("-e:End of line length must be between 1 and 132.\n",-1);
  233. X            break;
  234. X            /* 1..132 */
  235. X        case 'f': max_freq=atoi(optarg);
  236. X            if((max_freq<3)||(max_freq>255))
  237. X                abortit("-f:Maximum Frequency must be between 3 and 255.\n",-1);
  238. X            break;
  239. X        case 'i': max_len=atoi(optarg);
  240. X            if((max_len<1)||(max_len>132))
  241. X                abortit("-i:Inline Length must be between 1 and 132.\n",-1);
  242. X            break;
  243. X            /* 1..132 */
  244. X        case 'k':
  245. X            if( key_file ) {
  246. X                fprintf(stderr,"%s: Too many -k options\n",argv[0]);
  247. X                abortit("",1);
  248. X            }
  249. X            key_file=optarg;
  250. X            /* check for existance */
  251. X            if(access(key_file,R_OK)){
  252. X                perror(key_file);
  253. X                abortit("",-1);
  254. X            }        
  255. X             break;
  256. X        case 'n': max_nodes=atoi(optarg);
  257. X            if(max_nodes<0)
  258. X                abortit("-n:Number of nodes must be positive.\n",-1);
  259. X            break;                
  260. X        case 'o': maxk=atoi(optarg);
  261. X            if((maxk<3)||(maxk>TOP_K)){
  262. X                fprintf(stderr,"-o: Order must be between 3 and %d.\n",TOP_K);
  263. X                abortit("",-1);
  264. X            }
  265. X            break;
  266. X        case 'p':
  267. X             if( prime_file ) {
  268. X                fprintf(stderr, "%s: Too many -p options\n",argv[0]);
  269. X                abortit("",1);
  270. X            }
  271. X            prime_file=optarg;
  272. X            /* check for existance */
  273. X            if(access(prime_file,(R_OK|W_OK))){
  274. X                perror(prime_file);
  275. X                abortit("",-1);
  276. X            }        
  277. X            break;
  278. X        case 's': maxprime=atoi(optarg); break;
  279. X
  280. X        case 'z': 
  281. X             if( zero_freq_file ) {
  282. X                fprintf(stderr, "%s: Too many -z options\n",argv[0]);
  283. X                abortit("",1);
  284. X            }
  285. X            zero_freq_file=optarg;
  286. X            /* check for existance */
  287. X            if(access(zero_freq_file,(R_OK|W_OK))){
  288. X                perror(zero_freq_file);
  289. X                abortit("",-1);
  290. X            }        
  291. X            break;
  292. X        case 'A': add_space_mode=!add_space_mode;    break;
  293. X        case 'E': eol_only_mode=!eol_only_mode;        break;
  294. X        case 'L': eol_longer_mode=!eol_longer_mode;    break;
  295. X        case 'N': nl_truncate_mode=!nl_truncate_mode;    break;
  296. X        case 'P': pred_mode=!pred_mode;            break;
  297. X        case 'S': show_eol_mode=!show_eol_mode;        break;
  298. X        case 'g': login=!login;             break;
  299. X        case 'h': print_help();    abortit("",0);        break;
  300. X        case 'l': lisp_mode=!lisp_mode;            break;
  301. X        case 'm': silent=1;                break;
  302. X        case 'v': print_version();abortit("",0);    break;
  303. X        
  304. X
  305. X        default:
  306. X            fprintf(stderr,"\r%s: Use -h for help\r\n", argv[0]);
  307. X            abortit("",-1);
  308. X        }
  309. X    
  310. X    }
  311. X    
  312. X    if(zero_freq_file==NULL){
  313. X        strcpy(z_freq_buf, getenv("HOME"));
  314. X        strcat(z_freq_buf, ZERO_FREQ_FILE );
  315. X        zero_freq_file=z_freq_buf;
  316. X    }
  317. X    if(prime_file==NULL){
  318. X        strcpy(prime_buf, getenv("HOME"));
  319. X        strcat(prime_buf, PRIME_FILE );
  320. X        prime_file=prime_buf;
  321. X    }
  322. X    if(key_file==NULL){
  323. X        strcpy(key_buf, getenv("HOME"));
  324. X        strcat(key_buf, KEY_FILE );
  325. X        key_file=key_buf;
  326. X    }
  327. X
  328. X}
  329. END_OF_FILE
  330. if test 5852 -ne `wc -c <'command_line.c'`; then
  331.     echo shar: \"'command_line.c'\" unpacked with wrong size!
  332. fi
  333. # end of 'command_line.c'
  334. fi
  335. if test -f 'dt_complete.c' -a "${1}" != "-c" ; then 
  336.   echo shar: Will not clobber existing file \"'dt_complete.c'\"
  337. else
  338. echo shar: Extracting \"'dt_complete.c'\" \(13902 characters\)
  339. sed "s/^X//" >'dt_complete.c' <<'END_OF_FILE'
  340. X#include <alloca.h>        /* JJD: some other alloc may be better to use  */
  341. X#include <stdio.h>
  342. X#include <sys/file.h>
  343. X#include <sys/types.h>
  344. X#include <sys/dir.h>
  345. X#include <sys/stat.h>  
  346. X#include <sys/param.h>        /* JJD 3-89 added to get MAXPATHLEN and CANBSIZ*/
  347. X#include "file+rk.h"
  348. X#include "functions.h"
  349. X
  350. X
  351. X#define FILECOMPLETION 3    /* change if you need to change the binding of
  352. X                   filecompletion */
  353. X
  354. X/* MAX_FILENAME_LENGTH must be less than MAX_CMD_LINE_LENGTH (CANBSIZ, 256)*/
  355. X/*                                       */
  356. X/* dir.h MAXNAMLEN is 255 (+1 for char [])       JJD 3-89 #define       */
  357. X
  358. X#define MAX_DIR_TO_SEARCH    16        /* WARNING: just a guess!  */
  359. X#define MAX_FILES_TO_SAVE    1024        /* WARNING: just a guess!  */
  360. X#define MAX_FILENAME_LENGTH     MAXNAMLEN     /*          store bounds   */
  361. X#define MAX_PATHNAME_LENGTH     MAXPATHLEN
  362. X
  363. Xextern num_buffers;
  364. Xextern char *cursor_left;
  365. Xextern char output_string[];
  366. Xextern output_string_length;
  367. Xextern char pred_mode,pred_on_display;
  368. Xextern char pred_buff[];
  369. Xextern (*keymap[128][MAXEXTENSIONS]) ();
  370. X
  371. Xint run_ruptime (e) ED_STRUCT *e; {
  372. X  
  373. X      write (1, "\015\n", 2);                    /* JJD 3-89*/
  374. X      quietly_run_program_connected_to_standard_tty ("uptime"); /* JJD 3-89*/
  375. X      write (1, "Continue: ", 10);
  376. X      draw_current_edit_line (e);
  377. X      return OK;
  378. X}
  379. X
  380. X/* AN IDEA: a better way would look ahead a next char, if not this, put     */
  381. X/*        in the read buffer and return, else stay here - write (un)getc. */
  382. X  
  383. Xint file_completion (e) ED_STRUCT *e; {
  384. X      char *cwd,
  385. X           *getcwd(),
  386. X           *tdot,
  387. X           *tchar,chr,
  388. X           *f_name[MAX_FILES_TO_SAVE],        /* JJD 3-89 to ptrs, defines*/
  389. X           tstring[MAX_CMD_LINE_LENGTH + 1],
  390. X           de_name[MAX_FILENAME_LENGTH + 1],    /* JJD 3-89 dir entry name  */
  391. X           full_path[MAXPATHLEN];
  392. X
  393. X      DIR  *opendir(),
  394. X           *dir_pointer;
  395. X
  396. X      struct direct *readdir(),
  397. X                    *d_entry;
  398. X      int match=0,
  399. X          length,
  400. X          past_first=0,
  401. X          strncmp(),
  402. X          ful_path=0,
  403. X          count,
  404. X          cmatch,
  405. X          return_this = OK;                 /* JJD 2-89 added */
  406. X            /* now look for start of filename to match */
  407. X     for (tdot=e->dot;((*tdot != ' ') && (tdot != e->current_buffer));tdot--);
  408. X
  409. X            /* if we aren't at the start of the whole buffer
  410. X               then move ahead a char (to skip the space) */
  411. X      if (tdot != e->current_buffer) tdot++;
  412. X                        /* and save the string to look for */
  413. X      strcpy(tstring, tdot);
  414. X      for (tchar=tstring;((*tchar != '\/')&&(*tchar!='\0'));tchar++);
  415. X      if (*tchar == '\/') {
  416. X    ful_path = 1;
  417. X    strcpy(full_path,tstring);
  418. X    tchar=full_path;
  419. X    while (*tchar!='\0') tchar++;
  420. X    while ((*tchar!='\/') && (tchar != full_path)) tchar--;
  421. X        if (tchar != full_path) {
  422. X      *tchar = '\0';
  423. X      tchar++;strcpy(tstring,tchar);
  424. X    }
  425. X      }
  426. X      if (ful_path){
  427. X    cwd = full_path;
  428. X      }
  429. X      else {
  430. X    void    (*sig)();
  431. X    sig=signal(SIGCHLD,SIG_DFL); 
  432. X    getcwd(full_path);cwd=full_path;        /* get working directory */
  433. X    signal(SIGCHLD,sig); 
  434. X      }
  435. X      if ((dir_pointer = opendir(cwd)) == NULL){    /* and open it to look */
  436. X    write(1, "\07",1);
  437. X    return OK;
  438. X      }            /* now look for any matching filenames and
  439. X               increment match if we find one */
  440. X      d_entry=readdir(dir_pointer);
  441. X      for (; d_entry != NULL; d_entry = readdir(dir_pointer)){
  442. X        strcpy (de_name, d_entry->d_name);
  443. X    if (strncmp(tstring, de_name, strlen(tstring)) == 0){
  444. X         if ((strcmp(".", de_name) != 0) &&
  445. X             (strcmp("..", de_name) != 0)){    /* JJD 3-89 del . .. */
  446. X         f_name[match] = (char *) alloca (strlen(de_name) + 1);
  447. X         strcpy(f_name[match],de_name);
  448. X      if (++match >= MAX_FILES_TO_SAVE) {
  449. X          goto tomany;   /* JJD 3-89 forget about the rest of them */
  450. X      }
  451. X     }
  452. X    }
  453. X      }
  454. Xtomany:
  455. X      if (match == 0) {
  456. X    write(1,"\07",1);
  457. X    if (dir_pointer != NULL) closedir(dir_pointer); /* JJD 3-89 added if*/
  458. X    return OK;
  459. X      }
  460. X            /* else we found at least 1  match */      
  461. X      else {
  462. X        ssort (f_name, match); /* JJD 3-89, alpha */
  463. X    cmatch = 0;
  464. Xagain:    output_string_length = 0;
  465. X    if (!past_first) length=strlen(tstring);
  466. X    else {
  467. X      if (cmatch == 0) length=strlen(f_name[match-1]);
  468. X      else length=strlen(f_name[cmatch-1]);
  469. X    }
  470. X    if (ful_path) length = length + strlen(full_path)+1;
  471. X                              /* so move the cursor to the beginning
  472. X                 of the file name */
  473. X    for (; length; --length)
  474. X      tputs (cursor_left, ONE_LINE,append_to_output_string);
  475. X                              /* set current dot to beginning of the
  476. X                 file name and copy in the filename*/ 
  477. X    e->dot = tdot;
  478. X    if (ful_path){
  479. X      strcpy(e->dot,full_path);
  480. X      strcat(e->dot,"\/");
  481. X      strcat(e->dot,f_name[cmatch]);
  482. X    }
  483. X
  484. X/* JJD: WARNING: prev and next str ops could overflow ed_buff, should test */
  485. X
  486. X    else strcpy(e->dot,f_name[cmatch]);
  487. X                  /* reset dot to the end of the line */    
  488. X        if (e->mark > e->dot) e->mark += strlen (f_name[cmatch]);/*JJD 3-89*/
  489. X    e->dot += strlen(f_name[cmatch]);
  490. X
  491. X/* JJD: WARNING: prev and next dot resets could overflow ed_buff, as above */
  492. X
  493. X    if (ful_path) {
  494. X          if (e->mark > e->dot) e->mark += strlen(full_path)+1;
  495. X      e->dot += strlen(full_path)+1;
  496. X    }
  497. X                              /* and concatenate onto output string the
  498. X                 filename, write it to screen */
  499. X    if (ful_path) {
  500. X      display_string_into_output_string(full_path);
  501. X      display_string_into_output_string("\/");
  502. X    }
  503. X    display_string_into_output_string (f_name[cmatch]);
  504. X        if (cmatch == 0)length=strlen(f_name[match-1])-strlen(f_name[cmatch]);
  505. X    else length=strlen(f_name[cmatch-1])-strlen(f_name[cmatch]);
  506. X    for (count=0;count<length;count++){
  507. X      display_string_into_output_string(" ");
  508. X    }
  509. X    for (count=0;count<length;count++){
  510. X      tputs (cursor_left, ONE_LINE,append_to_output_string);
  511. X    }
  512. X    write (1, output_string, output_string_length);
  513. X    if (pred_mode) {                 /* JJD 2-89 added */
  514. X            make_a_prediction (pred_buff);
  515. X        if (pred_buff[0]) display_pred_buffer (e);
  516. X    }
  517. X    
  518. X    READ(0,&chr,1);
  519. X    chr &= 127;                     /* JJD 2-89 added */
  520. X        if (pred_on_display) erase_pred_buffer (e);      /* JJD 2-89 added */
  521. X    if (chr == FILECOMPLETION) {
  522. X      past_first = 1;
  523. X      if (cmatch < match-1) {
  524. X        cmatch++;
  525. X        goto again;
  526. X      }
  527. X      else {cmatch=0;goto again;}
  528. X    }
  529. X    else {
  530. X/* JJD: it would be better to ungetc and return */
  531. X          return_this = OK;                 /* JJD 2-89 added */
  532. X      e->current_input_char = chr;
  533. X      return_this = keymap[(int)chr][0](e); /* JJD 2-89 add return_this */
  534. X      if (dir_pointer != NULL) closedir(dir_pointer); /* JJD 3-89 add if*/
  535. X      return (return_this);               /* JJD 2-89 add return_this */
  536. X    }
  537. X      }
  538. X    }
  539. X
  540. X
  541. Xint command_completion (e) ED_STRUCT *e;{
  542. X  char *path_var,        /* points to the environment variable PATH */
  543. X       *tdot,
  544. X       *tchar, 
  545. X       chr,
  546. X       *paths[MAX_DIR_TO_SEARCH],        /* JJD 3-89 changed to ptrs */
  547. X           *f_name[MAX_FILES_TO_SAVE],
  548. X           tstring[MAX_CMD_LINE_LENGTH + 1],
  549. X           d_name[MAX_PATHNAME_LENGTH + 1],
  550. X           de_name[MAX_FILENAME_LENGTH + 1],
  551. X           t_name[MAX_PATHNAME_LENGTH + MAX_FILENAME_LENGTH + 1],
  552. X       *getenv();
  553. X  int  count,
  554. X       num_dirs=0,        /* number of directories to look in */
  555. X       current_search_directory,/* the current directory to look at */
  556. X       cmatch,
  557. X       match=0,
  558. X       length,
  559. X       past_first=0,
  560. X       return_this = OK;                 /* JJD 2-89 added */
  561. X
  562. XDIR  *opendir(),
  563. X     *dir_pointer;
  564. X
  565. Xstruct direct *readdir(),
  566. X              *d_entry;
  567. Xstruct stat   buf;                 /* JJD 3-89 added */
  568. X
  569. X                /* get the file name to match */  
  570. X  for (tdot=e->dot;((*tdot != ' ') && (tdot != e->current_buffer));tdot--);
  571. X  if (tdot != e->current_buffer) tdot++;
  572. X  strcpy(tstring, tdot);
  573. X
  574. X  path_var = getenv("PATH");
  575. X  if (path_var == NULL) {              /* JJD 3-89 added test */
  576. X    write(1,"\07",1);
  577. X    return OK;
  578. X  }
  579. X  else {
  580. X  tchar = path_var;                 /* skip the first :  */
  581. X/* JJD: this assumes a "normal" PATH, which it is 99.99% likely to be */
  582. X  if (path_var[0] == ':')  tchar++;         /* JJD 3-89 added if */
  583. X  while(*tchar != '\0'){
  584. X    count=0;                     /* JJD 3-89 stay in bounds*/
  585. X    while ((*tchar != ':') && (*tchar != '\0'))  d_name[count++] = *tchar++;
  586. X    if (*tchar == ':') tchar++;  
  587. X    d_name[count] = '\0';
  588. X    paths[num_dirs] = (char *) alloca (strlen(d_name) + 1);
  589. X    strcpy (paths[num_dirs], d_name);
  590. X    if (++num_dirs >= MAX_DIR_TO_SEARCH) {
  591. X      goto tomanydirs; /* JJD 3-89 forget the rest*/
  592. X    }
  593. X  }
  594. Xtomanydirs:
  595. X/* now have num_dirs directories to search for the command in */
  596. X/* JJD 3-89 NOW CHECKS FOR EXECUTE PERMISSION and NOT A DIRECTORY,      */
  597. X/*         THEN SORTS IN ALPHA ORDER, LEAVING IN DUPLICATED (are rare) */
  598. X
  599. X current_search_directory = 0;            /* JJD 3-89 changed <= to < */
  600. X for (;current_search_directory<num_dirs;current_search_directory++){
  601. X    strcpy (d_name, paths[current_search_directory]); strcat (d_name, "/");
  602. X    if ((dir_pointer = opendir(&paths[current_search_directory][0])) != NULL){
  603. X      d_entry=readdir(dir_pointer);
  604. X      for (;d_entry != NULL;d_entry = readdir(dir_pointer)){
  605. X        strcpy (de_name, d_entry->d_name);
  606. X        if (strncmp(tstring, de_name, strlen(tstring)) == 0){
  607. X         if ((strcmp(".", de_name) != 0) &&
  608. X             (strcmp("..", de_name) != 0)) {   /* JJD 3-89 del . .. */
  609. X      strcpy (t_name, d_name); strcat (t_name, de_name);
  610. X      if (access (t_name, X_OK) == 0) {        /* executable */
  611. X        if (stat(t_name,&buf) == 0){
  612. X         if ((buf.st_mode & S_IFMT) != S_IFDIR){ /* not a dir */
  613. X         f_name[match] = (char *) alloca (strlen(de_name) + 1);
  614. X         strcpy(f_name[match],de_name);
  615. X         if (++match >= MAX_FILES_TO_SAVE) {
  616. X            goto tomanyfiles; /* JJD 3-89 above */
  617. X         }
  618. X        }
  619. X       }
  620. X      }
  621. X     }
  622. X    }
  623. X      }
  624. X    }
  625. Xtomanyfiles:
  626. X    if (dir_pointer != NULL) closedir(dir_pointer);
  627. X  }
  628. X  if (match == 0) {
  629. X    write(1,"\07",1);
  630. X    return OK;
  631. X  }
  632. X              /* else we found at least 1  match */      
  633. X  else {
  634. X    ssort (f_name, match); /* JJD 3-89, alpha */
  635. X    cmatch = 0;
  636. Xagain:    output_string_length = 0;
  637. X    if (!past_first) length=strlen(tstring);
  638. X    else {
  639. X      if (cmatch == 0) length=strlen(f_name[match-1]);
  640. X      else length=strlen(f_name[cmatch-1]);
  641. X    }
  642. X    for (; length; --length)
  643. X      tputs (cursor_left, ONE_LINE,append_to_output_string);
  644. X/* set current dot to beginning of the file name and copy in the filename*/ 
  645. X    e->dot = tdot;
  646. X    strcpy(e->dot,f_name[cmatch]);
  647. X
  648. X/* JJD: WARNING: prev strcpy could overflow ed_buff, should test */
  649. X/* JJD: WARNING: next dot reset could overflow ed_buff, as above */
  650. X                /* reset dot to the end of the line */    
  651. X
  652. X    if (e->mark > e->dot) e->mark += strlen (f_name[cmatch]); /* JJD 3-89 */
  653. X    e->dot += strlen(f_name[cmatch]);
  654. X    display_string_into_output_string (f_name[cmatch]);
  655. X    if (cmatch == 0) length=strlen(f_name[match-1])-strlen(f_name[cmatch]);
  656. X    else length=strlen(f_name[cmatch-1])-strlen(f_name[cmatch]);
  657. X    for (count=0;count<length;count++){
  658. X      display_string_into_output_string(" ");
  659. X    }
  660. X    for (count=0;count<length;count++){
  661. X      tputs (cursor_left, ONE_LINE,append_to_output_string);
  662. X    }
  663. X    write (1, output_string, output_string_length);
  664. X    if (pred_mode) {                 /* JJD 2-89 added */
  665. X            make_a_prediction (pred_buff);
  666. X        if (pred_buff[0]) display_pred_buffer (e);
  667. X    }
  668. X    
  669. X    READ(0,&chr,1);
  670. X    chr &= 127;                     /* JJD 2-89 added */
  671. X        if (pred_on_display) erase_pred_buffer (e);      /* JJD 2-89 added */
  672. X    if (chr == (char)28) {                 /* JJD 2-89 made ^\*/
  673. X      past_first = 1;
  674. X      if (cmatch < match-1) {
  675. X        cmatch++;
  676. X        goto again;
  677. X      }
  678. X      else {cmatch=0;goto again;}
  679. X    }
  680. X    else {
  681. X/* JJD: it would be better to ungetc and return */
  682. X          return_this = OK;                 /* JJD 2-89 added */
  683. X      e->current_input_char = chr;
  684. X      return_this = keymap[(int)chr][0](e); /* JJD 2-89 add return_this */
  685. X      if (dir_pointer != NULL) closedir(dir_pointer); /* JJD 3-89 add if*/
  686. X      return (return_this);               /* JJD 2-89 add return_this */
  687. X    }
  688. X  }
  689. X  }
  690. X}
  691. X
  692. X
  693. Xset_mark (e) ED_STRUCT *e; {
  694. X  e->mark = e->dot;         /* JJD 3-89 mark intialized in set_up_buffers()*/
  695. X  e->current_ed_buff_ptr->mark = e->dot;              /* JJD 3-89 added */
  696. X}
  697. X
  698. Xshow_mark (e) ED_STRUCT *e; {
  699. X  int num_to_go;
  700. X  if (e->mark > e->dot){
  701. X    e->universal_argument = num_to_go = e->mark - e->dot;
  702. X    forward_char (e);
  703. X    sleep(1);                        /* JJD 3-89 change */
  704. X    e->universal_argument = num_to_go;
  705. X    backward_char (e);
  706. X  }
  707. X  else if (e->mark < e->dot){
  708. X    e->universal_argument = num_to_go = e->dot - e->mark;
  709. X    backward_char (e);
  710. X    sleep(1);                        /* JJD 3-89 change */
  711. X    e->universal_argument = num_to_go;
  712. X    forward_char (e);
  713. X  }
  714. X}
  715. X
  716. Xdelete_region_to_killbuffer (e) ED_STRUCT *e; {
  717. X
  718. X  int length;
  719. X
  720. X  if (e->dot > e->mark){
  721. X    length = e->dot - e->mark;
  722. X    strncpy(e->kill_buffer, e->mark, length);
  723. X    e->kill_buffer[length] = '\0';
  724. X    e->universal_argument = length;
  725. X    backward_char(e);
  726. X    e->universal_argument = length;
  727. X    e->mark = e->dot;
  728. X    return delete_char (e);
  729. X  }
  730. X  if (e->mark > e->dot){
  731. X    length = e->mark - e->dot;
  732. X    strncpy(e->kill_buffer, e->dot, length);
  733. X    e->kill_buffer[length] = '\0';
  734. X    e->universal_argument = length;
  735. X    e->mark = e->dot;
  736. X    return delete_char (e);
  737. X  }
  738. X  return OK;                        /* JJD 3-89 added */
  739. X}
  740. X
  741. X
  742. Xint strstr(look, lookin) char *look, *lookin;{
  743. X    int counter = 0;
  744. X    for (counter = 0; (counter < (strlen(lookin) - strlen(look))); counter++){
  745. X        if (strncmp(look, &lookin[counter], strlen(look)) == 0)
  746. X        return(0);
  747. X    }
  748. X    return(1);
  749. X}
  750. X
  751. X/*      
  752. Xsend_message(message)
  753. Xchar *message;
  754. X{
  755. X     ioctl (0, TIOCGETP, &new_stdin_sgttyb);
  756. X     ioctl (0, TIOCSETP, &old_stdin_sgttyb);
  757. X     printf ("recvd message:%s\n", message);
  758. X     ioctl (0, TIOCSETP, &new_stdin_sgttyb);
  759. X}
  760. X*/
  761. X
  762. Xssort (v, n) char *v[]; int n; {  /* JJD: Shell Sort alla p.108 K&R C book */
  763. X    int gap, i, j; char *temp;
  764. X    for (gap = n/2; gap > 0; gap /= 2)
  765. X        for (i= gap; i < n; i++)
  766. X            for (j = i-gap; j >= 0; j -= gap) {
  767. X                    if (strcmp(v[j], v[j+gap]) <= 0) break;
  768. X                temp = v[j];
  769. X                v[j] = v[j+gap];
  770. X                v[j+gap] = temp;
  771. X            }
  772. X}
  773. END_OF_FILE
  774. if test 13902 -ne `wc -c <'dt_complete.c'`; then
  775.     echo shar: \"'dt_complete.c'\" unpacked with wrong size!
  776. fi
  777. # end of 'dt_complete.c'
  778. fi
  779. if test -f 'file+rk.h' -a "${1}" != "-c" ; then 
  780.   echo shar: Will not clobber existing file \"'file+rk.h'\"
  781. else
  782. echo shar: Extracting \"'file+rk.h'\" \(1071 characters\)
  783. sed "s/^X//" >'file+rk.h' <<'END_OF_FILE'
  784. X#include <sys/param.h>        /* JJD 3-89 added to get MAXPATHLEN and CANBSIZ */
  785. Xchar *strcpy(), *strcat();                /* JJD 3-89 for lint */
  786. Xchar *gets(), *sprintf(), *malloc();            /* JJD 3-89 for lint */
  787. Xchar *sprintf();                    /* JJD 3-89 for lint */
  788. Xchar *index();
  789. X
  790. X#define OK                0
  791. X#define FINISHED_EDITING -1
  792. X#define FINISHED_BUT_DONT_ADD_CTRL_M -2
  793. X#define HAVE_CHAR -3
  794. X#define UNIVERSAL_ARGUMENT_MAXIMUM 256
  795. X#define MAX_CMD_LINE_LENGTH CANBSIZ
  796. X#define VERSION "1.0 August 21st 1989" 
  797. X#define RK_VERSION " 1.0 August 21st 1989"    
  798. X#define ONE_LINE (int)1            /* JJD 3-89 was int dummy for tputs */
  799. X
  800. X
  801. Xstruct ed_buffs {
  802. X    char string[MAX_CMD_LINE_LENGTH + 1];
  803. X    char *dot;
  804. X    char *mark;                        /* JJD 3-89 added */
  805. X    struct ed_buffs *next_ptr;
  806. X    struct ed_buffs *prev_ptr;
  807. X    };
  808. X
  809. Xtypedef struct _ed_struct {
  810. X    char current_input_char;
  811. X    int  universal_argument;
  812. X    char *current_buffer;
  813. X    char *dot;
  814. X    char *mark;
  815. X    char kill_buffer[MAX_CMD_LINE_LENGTH + 1];
  816. X    struct ed_buffs *current_ed_buff_ptr;
  817. X    } ED_STRUCT;
  818. X
  819. X#define MAXEXTENSIONS 12
  820. X
  821. END_OF_FILE
  822. if test 1071 -ne `wc -c <'file+rk.h'`; then
  823.     echo shar: \"'file+rk.h'\" unpacked with wrong size!
  824. fi
  825. # end of 'file+rk.h'
  826. fi
  827. if test -f 'freq.c' -a "${1}" != "-c" ; then 
  828.   echo shar: Will not clobber existing file \"'freq.c'\"
  829. else
  830. echo shar: Extracting \"'freq.c'\" \(5223 characters\)
  831. sed "s/^X//" >'freq.c' <<'END_OF_FILE'
  832. X/*       Written by John Darragh, Calgary Alberta, revised 3-89.
  833. X *
  834. X * freq.c: tabulates ASCII character frequencies from stdin and outputs
  835. X *         freq sorted ASCII chars on the stdout in a number of formats.
  836. X *
  837. X *       intended as a utility for rk_button to create its zero_freq
  838. X *       startup FREQ_DATA_FILE and/or default zero_freq[] char array.
  839. X *
  840. X *       this info is used by rk to predict chars it hasn't yet added
  841. X *       to it's model (either by file priming or user command input).
  842. X *
  843. X *       it puts any unseen chars in ASCII sequence, and puts any un-
  844. X *       represented control codes (including DEL) at the end.
  845. X *
  846. X * defaults:    outputs 256 chars as 128 ASCII char/NL pairs.
  847. X *        (the NLs are just for readabilities sake, rk ignores them.)
  848. X *
  849. X * options:
  850. X *       -c   write output as a C array for inclusion in programs.
  851. X *         -n   don't put a NL after each of the 128 chars output.
  852. X *        (intended for future revision to init_reactive() which
  853. X *         would halve the freq file size from 256 -- saves space)
  854. X *         <filename>   read data from file other than stdin.
  855. X */
  856. X
  857. X#include <stdio.h>
  858. X
  859. X#define TRUE    1
  860. X#define FALSE   0
  861. X#define MAXTABLE        128    /* the size of the ASCII character set     */
  862. X
  863. XFILE    * infile = stdin;    /* for <filename> arg */
  864. Xchar    no_nls   = FALSE;    /* -n option above    */
  865. Xchar    c_array  = FALSE;    /* -c option above    */
  866. Xint     ch_table[MAXTABLE][2];    /* [][0] are labels, [][1] are freq counts */
  867. X
  868. Xmain (argc, argv)
  869. Xint argc;
  870. Xchar **argv;
  871. X{
  872. X        char chr;  register int i, j;  int gap, temp[2];
  873. X
  874. X        get_args (argc, argv);  /* may change infile, no_nls, c_array      */
  875. X                /* init table labels and do the freq count */
  876. X    for (i=0; i<MAXTABLE; i++) {
  877. X         ch_table[i][0] = i;     /* the ACSII code           */
  878. X         ch_table[i][1]= -(i+1); /* ensure ASCII order for 0-freqs */
  879. X    }                    /* by intially -ve freq counts */
  880. X        while ((chr = getc(infile)) != EOF) {
  881. X        chr &= 0177;
  882. X        if (ch_table[(int)chr][1] < 0)  /* seen, so fix -ve freqs */
  883. X            ch_table[(int)chr][1] = 0;
  884. X        ch_table[(int)chr][1]++;
  885. X    }
  886. X    for (i=0; i<32; i++) {
  887. X        if (ch_table[i][1] < 0)     /* ensure 0-freq control codes */
  888. X            ch_table[i][1] -= MAXTABLE;       /* end up at the end */
  889. X    }
  890. X    if (ch_table[MAXTABLE-1][1] < 0)     /* ensure same for DEL char   */
  891. X            ch_table[MAXTABLE-1][1] -= MAXTABLE;
  892. X                /* frequency sort the thing (shell sort)   */
  893. X    for (gap = MAXTABLE/2; gap > 0; gap /= 2)
  894. X        for (i= gap; i < MAXTABLE; i++)
  895. X            for (j = i-gap; j >= 0; j -= gap) {
  896. X                    if (ch_table[j][1] <= ch_table[j+gap][1])
  897. X                     break;
  898. X                temp[0] = ch_table[j][0];
  899. X                temp[1] = ch_table[j][1];
  900. X                ch_table[j][0] = ch_table[j+gap][0];
  901. X                ch_table[j][1] = ch_table[j+gap][1];
  902. X                ch_table[j+gap][0] = temp[0];
  903. X                ch_table[j+gap][1] = temp[1];
  904. X            }
  905. X                /* output a compilable "C" character array */
  906. X    if (c_array) {
  907. Xprintf ("static char zero_freq[128] = {         /* by a user supplied $home/file */\n");
  908. X        for (i=MAXTABLE-1; i>=0; i--) {
  909. X        switch (chr = (char)(ch_table[i][0] & 127)) {
  910. X        case '\n':  printf ("  \'\\n\',");  break;
  911. X        case '\t':  printf ("  \'\\t\',");  break;
  912. X        case '\b':  printf ("  \'\\b\',");  break;
  913. X        case '\r':  printf ("  \'\\r\',");  break;
  914. X        case '\f':  printf ("  \'\\f\',");  break;
  915. X        case '\\':  printf ("  \'\\\\\',"); break;
  916. X        case '\'':  printf ("  \'\\\'\',"); break;
  917. X        case  127:  printf ("\'\\%03o\',", (int)chr); break;
  918. X        default:    if (chr < 32) printf (" \'\\%02o\',", (int)chr);
  919. X                else       printf ("   \'%1c\',", chr); break;
  920. X            }
  921. X        if (((i%8) == 0) && (i != 0)) printf ("\n");
  922. X        }
  923. X        printf ("};\n");
  924. X                /* otherwise just put out sorted chars */
  925. X        } else
  926. X        for (i=MAXTABLE-1; i>=0; i--)
  927. X            if (no_nls) printf ("%c",   (char)ch_table[i][0]);
  928. X        else        printf ("%c\n", (char)ch_table[i][0]);
  929. X
  930. X        abortit ("", 0);
  931. X}
  932. X
  933. X
  934. Xstatic char *options = " -n[no_nls] -c[c_array] <input file>\n";
  935. X
  936. Xstatic get_args (argc, argv)   /* may change infile */
  937. Xint argc;
  938. Xchar **argv;
  939. X/*
  940. X * Get any command arguments and set any appropriate
  941. X * global flags and variables.
  942. X */
  943. X{
  944. X    static char usage[256] = "usage: ";
  945. X
  946. X    strcat (usage, &argv[0][0]);        /* fill in name of object file */
  947. X    strcat (usage, options);
  948. X
  949. X    while ((argc > 1) && (argv[1][0] == '-')) {
  950. X        switch (argv[1][1]) {
  951. X
  952. X      case 'c': case 'C':               /* turn on C char array output */
  953. X                        c_array = TRUE;
  954. X                        break;
  955. X
  956. X      case 'n': case 'N':               /* turn on "no NL" output mode */
  957. X                        no_nls = TRUE;
  958. X                        break;
  959. X
  960. X      default:          abortit (usage, -1);
  961. X
  962. X        } /*switch*/
  963. X        argc--; argv++;
  964. X
  965. X    }
  966. X    if (argc == 2) {            /* file argument present */
  967. X        if ((infile = fopen (&argv[1][0], "r")) == NULL) {
  968. X            fprintf (stderr, "cannot open: %s\n", &argv[1][0]);
  969. X            abortit (usage, -1);
  970. X        }
  971. X    } else if (argc != 1) abortit (usage, -1);
  972. X}/*get_args*/
  973. X
  974. X
  975. Xstatic abortit (message, status)
  976. Xchar *message;
  977. Xint status;
  978. X/*
  979. X * All program terminations are through this routine.
  980. X * It prints an optional message, then exits with
  981. X * the parameter status.
  982. X */
  983. X{
  984. X    fprintf (stderr, "%s", message);
  985. X    fflush (stderr);
  986. X    exit (status);
  987. X}/*abortit*/
  988. END_OF_FILE
  989. if test 5223 -ne `wc -c <'freq.c'`; then
  990.     echo shar: \"'freq.c'\" unpacked with wrong size!
  991. fi
  992. # end of 'freq.c'
  993. fi
  994. if test -f 'functions.h' -a "${1}" != "-c" ; then 
  995.   echo shar: Will not clobber existing file \"'functions.h'\"
  996. else
  997. echo shar: Extracting \"'functions.h'\" \(1578 characters\)
  998. sed "s/^X//" >'functions.h' <<'END_OF_FILE'
  999. Xint    append_to_output_string();
  1000. Xint     accept_forward_char();
  1001. Xint     accept_forward_word();
  1002. Xint     accept_to_end_of_line();
  1003. Xint     backspace_char();
  1004. Xint     backspace_word();
  1005. Xint     backward_char();
  1006. Xint     backward_paren();
  1007. Xint     backward_word();
  1008. Xint     beginning_of_line();
  1009. Xint    BOGUS();
  1010. Xint     capitalize_word();
  1011. Xint     clear_display();
  1012. Xint     close_paren();
  1013. Xint     command_completion();
  1014. Xint     dash_to_ul_word();
  1015. Xint     delete_char();
  1016. Xint     delete_region_to_killbuffer();
  1017. Xint     delete_word();
  1018. Xint     describe_bindings();
  1019. Xint    describe_arguments();
  1020. Xint     discard_current_edit_line();
  1021. Xint     discard_rest_of_line();
  1022. Xint     end_of_line();
  1023. Xint     file_completion();
  1024. Xint     finish_editing_line();
  1025. Xint     forward_char();
  1026. Xint     forward_paren();
  1027. Xint     forward_word();
  1028. Xint     increment_universal_argument();
  1029. Xint     insert_interrupt_char();
  1030. Xint     insert_quit_char();
  1031. Xint     insert_start_char();
  1032. Xint     insert_stop_char();
  1033. Xint     insert_suspend_char();
  1034. Xint     lowercase_word();
  1035. Xint     meta_prefix();
  1036. Xint     next_line();
  1037. Xint     next_pred();
  1038. Xint     open_paren();
  1039. Xint     previous_line();
  1040. Xint     previous_pred();
  1041. Xint     prime_from_file();
  1042. Xint     quote_char();
  1043. Xint     run_mesg();
  1044. Xint     run_pp();
  1045. Xint     run_ruptime();
  1046. Xint     run_talk();
  1047. Xint     run_tty_program();
  1048. Xint     run_write();
  1049. Xint     self_insert();
  1050. Xint     set_mark();
  1051. Xint     show_free_nodes();
  1052. Xint     show_mark();
  1053. Xint     show_version();
  1054. Xint    toggle_add_space_mode();
  1055. Xint    toggle_show_eol_mode();
  1056. Xint     toggle_eol_longer_mode();
  1057. Xint     toggle_eol_only_mode();
  1058. Xint     toggle_lisp_mode();
  1059. Xint     toggle_nl_truncate_mode();
  1060. Xint     toggle_pred_mode();
  1061. Xint     twiddle_chars();
  1062. Xint     ul_to_dash_word();
  1063. Xint     uppercase_word();
  1064. Xint     yank_from_kill_buffer();
  1065. END_OF_FILE
  1066. if test 1578 -ne `wc -c <'functions.h'`; then
  1067.     echo shar: \"'functions.h'\" unpacked with wrong size!
  1068. fi
  1069. # end of 'functions.h'
  1070. fi
  1071. if test -f 'myabspath.c' -a "${1}" != "-c" ; then 
  1072.   echo shar: Will not clobber existing file \"'myabspath.c'\"
  1073. else
  1074. echo shar: Extracting \"'myabspath.c'\" \(869 characters\)
  1075. sed "s/^X//" >'myabspath.c' <<'END_OF_FILE'
  1076. X/* Mark James 89/5/24*/
  1077. X
  1078. X
  1079. X#include "myabspath.h"
  1080. X#include <pwd.h>
  1081. X#include <stdio.h>
  1082. X#include <ctype.h>
  1083. X#include <strings.h>
  1084. X
  1085. X
  1086. X/* returns 0 on success, NO_HOME if getenv("HOME") fails, NO_USER if ~user does not exist */
  1087. X
  1088. Xmyabspath(path,buff)
  1089. Xchar *path;
  1090. Xchar *buff;
  1091. X{
  1092. X    char *homedir;
  1093. X    char *getenv();
  1094. X    char username[MAX_USER_NAME];
  1095. X    int i;
  1096. X    struct passwd *pwd;
  1097. X
  1098. X    while (isspace(path[0])&&path[0])
  1099. X        path++;
  1100. X    if(path[0]=='~'){
  1101. X        path++;
  1102. X        if((path[0]=='/') || (path[0]==0)){
  1103. X            if((homedir=getenv("HOME"))==0)
  1104. X                return(NO_HOME);
  1105. X            strcpy(buff,homedir);
  1106. X            strcat(buff,path);
  1107. X            return(0);
  1108. X        }
  1109. X        else
  1110. X        {
  1111. X            for(i=0;(path[0]!='/')&&(path[0]!=0);i++,path++)
  1112. X                username[i]=path[0];
  1113. X            username[i]=0;
  1114. X            if((pwd=getpwnam(username))==0)
  1115. X                return(NO_USER);
  1116. X            strcpy(buff,pwd->pw_dir);
  1117. X            strcat(buff,path);        
  1118. X        }
  1119. X    }
  1120. X    else
  1121. X    {
  1122. X        strcpy(buff,path);
  1123. X        return(0);
  1124. X    }
  1125. X}
  1126. X
  1127. X
  1128. X
  1129. X
  1130. END_OF_FILE
  1131. if test 869 -ne `wc -c <'myabspath.c'`; then
  1132.     echo shar: \"'myabspath.c'\" unpacked with wrong size!
  1133. fi
  1134. # end of 'myabspath.c'
  1135. fi
  1136. if test -f 'myabspath.h' -a "${1}" != "-c" ; then 
  1137.   echo shar: Will not clobber existing file \"'myabspath.h'\"
  1138. else
  1139. echo shar: Extracting \"'myabspath.h'\" \(64 characters\)
  1140. sed "s/^X//" >'myabspath.h' <<'END_OF_FILE'
  1141. X#define NO_HOME -1
  1142. X#define NO_USER -2
  1143. X
  1144. X#define MAX_USER_NAME 40
  1145. END_OF_FILE
  1146. if test 64 -ne `wc -c <'myabspath.h'`; then
  1147.     echo shar: \"'myabspath.h'\" unpacked with wrong size!
  1148. fi
  1149. # end of 'myabspath.h'
  1150. fi
  1151. if test -f 'rk_button.c' -a "${1}" != "-c" ; then 
  1152.   echo shar: Will not clobber existing file \"'rk_button.c'\"
  1153. else
  1154. echo shar: Extracting \"'rk_button.c'\" \(7389 characters\)
  1155. sed "s/^X//" >'rk_button.c' <<'END_OF_FILE'
  1156. X#include "rk_button.h"             
  1157. X#include "file+rk.h"
  1158. X
  1159. Xextern maxk;
  1160. Xextern max_nodes;
  1161. Xextern max_freq;
  1162. Xint maxprime=16*1024;
  1163. X
  1164. X                     /** shared with rk_file/file+rk **/
  1165. Xchar   first[MAX_SET],             /* the first letter of each pred */
  1166. X       context[MAX_CMD_LINE_LENGTH] = "\07",   /* last chars entered */
  1167. X       old_context[MAX_CMD_LINE_LENGTH] = "\07";
  1168. XBuffer Buf, CBuf;             /* ptrs into the model k levels  */
  1169. Xchar   *prime_file;             /* file to prime from and log to */
  1170. Xint    next_free = 0;             /* index of next free node avail */
  1171. Xlong   psize;                 /* # chars to prime from prime_file*/
  1172. X                     /* zero freqs, maybe overwritten */
  1173. Xstatic char zero_freq[128] = {         /* by a user supplied $home/file */
  1174. X  '\n',   ' ',   'e',   's',   't',   'r',   'a',   'l',
  1175. X   'n',   '.',   'c',   'i',   'm',   'o',   'd',   'h',
  1176. X   'p',   'u',   'f',   'b',   'w',   'g',   '-',   'y',
  1177. X   '/',   'v',   'k',   '*',   'x',   '5',   '1',   '2',
  1178. X   '4',   '>',   'q', '\07',   '3',   'z',   '0',   'j',
  1179. X   'M',   'I',   '6',  '\'',   'E',   '~',   'A',   ',',
  1180. X   'S',   'D',   'R',   '?',   'C',   '|',   'B',   'T',
  1181. X   'P',   'U',   '!',   '_',   '<',   'N',   '8',   '@',
  1182. X   '&',   '7',  '\\',   '"',   'J',   ')',   '(',   '[',
  1183. X   ']',   'F',   'L',   ':',   'O',   'K',   '9',   'H',
  1184. X   '+',   '$',   'W',   'Y',   '=',   'G',   ';',   '^',
  1185. X   '{',   'X',   'Q',   '#',   '}',   'V',   '%',   'Z',
  1186. X   '`',  '\b',  '\t', '\26', '\00', '\01', '\02', '\03',
  1187. X '\04', '\05', '\06', '\13',  '\f',  '\r', '\16', '\17',
  1188. X '\20', '\21', '\22', '\23', '\24', '\25', '\27', '\30',
  1189. X '\31', '\32', '\33', '\34', '\35', '\36', '\37','\177',};
  1190. X
  1191. Xchar *zero_freq_file;
  1192. X
  1193. Xstatic char    pred_set[MAX_SET];    /* flags chars already in first[]*/
  1194. X
  1195. Xstatic NodePtr free_nodes;         /* now use malloc to get at init */
  1196. Xstatic NodePtr root;             /* the root of the k model trie  */
  1197. X
  1198. XNodePtr create_node() {             /* return ptr to a new node or abort */
  1199. X    if (next_free >= max_nodes) {
  1200. X        char *malloc(); NodePtr nptr;
  1201. X        nptr = (NodePtr) malloc((unsigned) sizeof(Node));
  1202. X        if (nptr == nil)         /* SHOULD FORGET AND CONTINUE ON */
  1203. X            abortit ("Out of memory in create_node.\n",-1);
  1204. X        next_free++;              /* just for show_free_nodes */
  1205. X            return(nptr);              /* if more are needed   */
  1206. X    } else  return(&free_nodes[next_free++]); /* first nodes upto MAX */
  1207. X}
  1208. X
  1209. XNodePtr move_up(nptr, c) NodePtr nptr; char c; {
  1210. X
  1211. X    NodePtr xptr, fxptr, last_ptr, last_fptr; int state;
  1212. X
  1213. X    if (nptr == nil) xptr = nil;
  1214. X    else {
  1215. X         if (nptr->up == nil) state = START;
  1216. X         else {
  1217. X            fxptr = xptr = nptr->up;  last_fptr = last_ptr = nil;
  1218. X            state = SCANNING;
  1219. X            do {
  1220. X               if (xptr == nil) state = END;
  1221. X               else {
  1222. X                  if (fxptr->count > xptr->count) {
  1223. X             last_fptr = last_ptr;  fxptr = xptr; }
  1224. X                  if (xptr->value == c) {
  1225. X                     state = FOUND;
  1226. X                     if (fxptr != xptr) {
  1227. X                        if (last_fptr == nil) nptr->up = xptr;
  1228. X                        else last_fptr->next = xptr;
  1229. X                        last_ptr->next = xptr->next;  xptr->next = fxptr;
  1230. X                  }  } else { last_ptr = xptr;  xptr = xptr->next; }
  1231. X            }  } while (state == SCANNING);
  1232. X         }
  1233. X         switch (state) {
  1234. X         case FOUND:
  1235. X         if (++(xptr->count) == max_freq) { /* Forgets on halving 1 */
  1236. X            /*last_fptr =*/ fxptr = nptr->up;
  1237. X            while (fxptr != nil) {         /* JJD 9-86 */
  1238. X            fxptr->count++;
  1239. X            fxptr->count >>= 1;
  1240. X/* DOESN'T FORGET A NODES SUBTREE NODES YET SO DON'T DO IT */
  1241. X/* MAY HAcE TO INCREASE max_freq TO REDUCE HALcING & OcERHEAD */
  1242. X/*             if (fxptr->count == 0) {
  1243. X                last_fptr->next = fxptr->next;
  1244. Xwrite(1,"1/2 free\n",9);
  1245. X                Free(fxptr);
  1246. X                fxptr = last_fptr->next;
  1247. X            } else {
  1248. X                last_fptr = fxptr; */
  1249. X                fxptr = fxptr->next;
  1250. X            
  1251. X            }
  1252. X        }
  1253. X        break;
  1254. X         case START: case END:
  1255. X               xptr = create_node();
  1256. X               xptr->value = c;  xptr->count = 1;
  1257. X               xptr->up = xptr->next = nil;
  1258. X           if (state == START) nptr->up = xptr;
  1259. X           else last_ptr->next = xptr;
  1260. X               break;
  1261. X    }}
  1262. X    return (xptr);
  1263. X}
  1264. X
  1265. Xfind_first(buf) Buffer buf; { /* find 1st char of all pred in context */
  1266. X
  1267. X    int i, order = 0; NodePtr xptr; char *p;
  1268. X
  1269. X        for (p= &pred_set[0]; p< &pred_set[MAX_SET]; p++) *p = '\0';
  1270. X    for (i=maxk-1; i>=0; i--) {      
  1271. X        if (buf[i] != nil)
  1272. X        if (buf[i]->up != nil) {
  1273. X        xptr = buf[i]->up;
  1274. X        while (xptr != nil) {
  1275. X            if (!pred_set[(int)xptr->value]) {
  1276. X            pred_set[(int)xptr->value]++;
  1277. X            first[order++] = xptr->value;
  1278. X            }  
  1279. X            xptr = xptr->next;
  1280. X    }   }    }
  1281. X        for (p= &zero_freq[0]; p< &zero_freq[MAX_SET]; p++)
  1282. X        if (!pred_set[(int)*p]) first[order++] = *p;
  1283. X}
  1284. X
  1285. Xchar first_pred(buf) Buffer buf; {
  1286. X    int i = maxk-1;
  1287. X    for (;;) {
  1288. X    if (buf[i] != nil)
  1289. X        if (buf[i]->up != nil) return (buf[i]->up->value);
  1290. X    if (i == 0) return((char)1);
  1291. X    i--;
  1292. X    }
  1293. X}
  1294. X
  1295. XNodePtr scan_up(nptr,c) NodePtr nptr; char c; {
  1296. X
  1297. X    NodePtr xptr;
  1298. X    if (nptr == nil) return(nil);
  1299. X    else {
  1300. X        xptr = nptr->up;
  1301. X        for (;;) {
  1302. X            if (xptr == nil) return (nil);
  1303. X            else if (xptr->value == c) return(xptr);
  1304. X            else xptr = xptr->next;
  1305. X    }    }
  1306. X}
  1307. X
  1308. Xinit_reactive() {
  1309. X    double atof(), u;
  1310. X    register int i; FILE *from, *popen();
  1311. X    char c, *b, *rindex(), tbuf[256], home[128];
  1312. X    char cbuf[32+1], *cstart, *cend, *end; int full; long size;
  1313. X
  1314. X                /* get a bunch of nodes for starters        */
  1315. X    free_nodes = (NodePtr) malloc((unsigned) (max_nodes * sizeof(Node)));
  1316. X        if (free_nodes == nil) {
  1317. X            sprintf (tbuf, "cannot allocate %d nodes.\n", max_nodes);
  1318. X            abortit (tbuf, -1);
  1319. X    }
  1320. X                /* set up root and pointers into model      */
  1321. X    CBuf[0] = Buf[0]        = root = create_node();
  1322. X    root->up    = root->next = nil;
  1323. X    root->count = 1;
  1324. X    for (i=1; i<=maxk; i++) Buf[i] = nil;
  1325. X        if ((from = fopen (zero_freq_file, "r")) != NULL) {
  1326. X        i = 0;
  1327. X        while (((int)(c = getc(from))) != EOF) {
  1328. X            zero_freq[i++] = c;
  1329. X            if (((int)(c = getc(from))) == EOF) break; /* del NL */
  1330. X            if (i>127) break;             /* test if okay */
  1331. X        }
  1332. X    } /* else use built in zero_freq[] */
  1333. X                /* calc amount to prime, sys load dependent*/
  1334. X    if ((from = popen ("uptime", "r")) != NULL) {
  1335. X        fgets (tbuf, 128, from);
  1336. X        b = rindex (tbuf, ':');  b++;
  1337. X        u = atof(b);
  1338. X        pclose (from);
  1339. X    } else u = 1.0;
  1340. X    if (u > 1.0) psize = (long) ((double)((double) maxprime) / u);
  1341. X    else         psize = (long) (maxprime);
  1342. X                /* if user has .rk.log_file, prime from it */
  1343. X        if ((from = fopen (prime_file, "r")) != NULL) {
  1344. X        fseek (from, 0L, 2);        /* find out how long it is */
  1345. X        size = ftell (from);
  1346. X        if (size > psize) {            /* prime max chars at end  */
  1347. X        fseek (from, -psize, 2);           /* start after ^G mark  */
  1348. X/* on second thought, if not "logged" by rk, may be no ^Gs in the file     */
  1349. X/*             while ((((int)(c = getc(from))) != EOF) && (c != '\07')) ;*/
  1350. X        } else rewind (from);
  1351. X        cstart = cend = cbuf; end = &cbuf[maxk]; full = 0;
  1352. X        while (((int)(c = getc(from))) != EOF) {
  1353. X        *cstart = c;
  1354. X        if (full) { ++cstart; if (cstart > end) cstart = cbuf; }
  1355. X        if (++cend > end) { cend = cbuf; full = 1; }
  1356. X        *cend = '\0';
  1357. X            for (i=maxk; i>0; i--) Buf[i] = move_up(Buf[i-1],c);
  1358. X        }
  1359. X        i = 0;        /* align the context */
  1360. X        while (cstart != cend) {
  1361. X        context[i] = old_context[i] = *cstart++; i++;
  1362. X        if (cstart > end) cstart = cbuf;
  1363. X        }
  1364. X        fclose (from);    
  1365. X    }
  1366. X}
  1367. X
  1368. END_OF_FILE
  1369. if test 7389 -ne `wc -c <'rk_button.c'`; then
  1370.     echo shar: \"'rk_button.c'\" unpacked with wrong size!
  1371. fi
  1372. # end of 'rk_button.c'
  1373. fi
  1374. if test -f 'rk_button.h' -a "${1}" != "-c" ; then 
  1375.   echo shar: Will not clobber existing file \"'rk_button.h'\"
  1376. else
  1377. echo shar: Extracting \"'rk_button.h'\" \(987 characters\)
  1378. sed "s/^X//" >'rk_button.h' <<'END_OF_FILE'
  1379. X/* definitions for rk_button, written by John Darragh, Calgary, revised 3-89
  1380. X */
  1381. X#include <ctype.h>
  1382. X#include <stdio.h>
  1383. X
  1384. X#define false        0
  1385. X#define true        1
  1386. X#define nil        ((NodePtr)0)
  1387. X#define MAX_SET        128         /* max # of different symbols (ASCII) */
  1388. X#define TOP_K        10
  1389. X
  1390. X#define START        0            /* values for state variables         */
  1391. X#define SCANNING    1
  1392. X#define FOUND        2
  1393. X#define END        3
  1394. X
  1395. Xtypedef struct node {                /** variable length Markov tree node **/
  1396. X        char           value;        /*  ASCII symbol value (to MAX_SET-1) */
  1397. X        char           count;        /*  frequency count (to max_freq)     */
  1398. X        struct node    *next;        /*  alternative predictions at this k */
  1399. X        struct node    *up;          /*  next k level up, eg 3 points to 4 */
  1400. X} Node;
  1401. Xtypedef Node  *NodePtr;              /** a pointer to a tree node      **/
  1402. Xtypedef NodePtr Buffer[TOP_K+1];     /*  k ptrs into the tree k contexts   */
  1403. X
  1404. XNodePtr scan_up(), move_up();
  1405. Xchar    first_pred();
  1406. END_OF_FILE
  1407. if test 987 -ne `wc -c <'rk_button.h'`; then
  1408.     echo shar: \"'rk_button.h'\" unpacked with wrong size!
  1409. fi
  1410. # end of 'rk_button.h'
  1411. fi
  1412. if test -f 'rk_file.c' -a "${1}" != "-c" ; then 
  1413.   echo shar: Will not clobber existing file \"'rk_file.c'\"
  1414. else
  1415. echo shar: Extracting \"'rk_file.c'\" \(3279 characters\)
  1416. sed "s/^X//" >'rk_file.c' <<'END_OF_FILE'
  1417. X/* "FILE's" link to rk_button, written by John Darragh, Calgary, revised 3-89
  1418. X *
  1419. X * these are the main function used by file+rk.c to generate predictions
  1420. X */
  1421. X#include "rk_button.h"
  1422. X#include "file+rk.h"
  1423. X
  1424. Xextern int     pred_number;              /* Defined in file+rk.c   */
  1425. Xextern char     nl_truncate_mode,
  1426. X         eol_only_mode,
  1427. X         eol_longer_mode;
  1428. X         show_eol_mode;
  1429. Xextern ED_STRUCT editor_data;
  1430. X
  1431. Xextern char   first[MAX_SET],              /* Defined in rk_button.c */
  1432. X              context[MAX_CMD_LINE_LENGTH],
  1433. X              old_context[MAX_CMD_LINE_LENGTH];
  1434. Xextern Buffer Buf, CBuf;
  1435. Xextern char   *prime_file;
  1436. Xextern char   pred_on_display;
  1437. Xint max_len=8;
  1438. Xint max_eol=30;
  1439. Xint maxk=8;
  1440. Xint max_freq=127;
  1441. Xint max_nodes=256*1024;              /* 256K */
  1442. X
  1443. X
  1444. Xstatic char   temp[1024];              /* scratch string buf */
  1445. X
  1446. X
  1447. Xmake_a_prediction (s) char *s; {    /* sets s to the current prediction */
  1448. X
  1449. X    char *a = temp; int length, i;
  1450. X    
  1451. X    if (eol_only_mode && *(editor_data.dot)) { *s = '\0'; return; }
  1452. X        strcpy (temp, context);
  1453. X    strcat (temp, editor_data.current_buffer);
  1454. X    length = strlen (temp) - strlen (editor_data.dot);
  1455. X    temp[length] = '\0';
  1456. X    if (length > maxk) a = &temp[length - maxk];
  1457. X
  1458. X    if (strcmp (old_context, a)) pred_number = 0;
  1459. X    strcpy (old_context, a);
  1460. X    
  1461. X    for (i=1; i<=maxk; i++) CBuf[i] = nil;
  1462. X    while (*a) {
  1463. X        for (i=maxk; i>0; i--) CBuf[i] = scan_up(CBuf[i-1],*a);
  1464. X        a++;
  1465. X    }
  1466. X    find_first(CBuf);
  1467. X        build_menu(CBuf, s);
  1468. X    }
  1469. X
  1470. Xupdate_the_model (s) char *s; { /* adds s into the model & updates log */
  1471. X
  1472. X    char *a = s, *c = s; int length, i; FILE *to;
  1473. X
  1474. X    if (strlen(s) < maxk) {
  1475. X            strcpy (temp, context);
  1476. X            strcat (temp, s);
  1477. X        length = strlen (temp);
  1478. X        if (length > maxk) a = &temp[length - maxk];
  1479. X        else a = temp;
  1480. X    }
  1481. X    strcpy (context, a);
  1482. X    while (*c) {
  1483. X        for (i=maxk; i>0; i--) Buf[i] = move_up(Buf[i-1],*c);
  1484. X        c++;
  1485. X    }            /* do not save "empty" lines in the log file */
  1486. X                    /* reopen to append log, otherwise create it */
  1487. X        if (s[0] != '\n') {    /* now log can be manipulated and still used */
  1488. X        if ((to = fopen (prime_file, "a")) == NULL) {
  1489. X        sprintf (temp, "cannot reopen or create: %s\n", prime_file);
  1490. X        abortit (temp, -1);
  1491. X        }
  1492. X        fputs (s, to); fflush (to);
  1493. X        fclose(to);
  1494. X    }
  1495. X}
  1496. X
  1497. Xbuild_menu(buf,s) Buffer buf; char *s; { /* fill out prediction in s */
  1498. X
  1499. X    int i,j,length; Buffer tbuf; char *bptr = s, c;
  1500. X
  1501. X    if (eol_longer_mode && !(*(editor_data.dot))) {
  1502. X        length = max_eol
  1503. X                 - get_display_length(editor_data.current_buffer);
  1504. X        if (length < max_len) length = max_len;
  1505. X    } else length = max_len;
  1506. X
  1507. X    c = first[pred_number];
  1508. X    for (i=0; i<=maxk; i++) tbuf[i] = buf[i];
  1509. X    for (i=1; i<=length; i++) {
  1510. X        if (show_eol_mode)
  1511. X            *bptr++ = c;
  1512. X        else if((c != '\n') || (i==1))
  1513. X            *bptr++ = c;
  1514. X        if (nl_truncate_mode && (c == '\n')) goto bp;
  1515. X        for (j=maxk; j>=1; j--) tbuf[j] = scan_up (tbuf[j-1],c);
  1516. X        c = first_pred(tbuf);
  1517. X        }
  1518. Xbp:    *bptr = '\0';
  1519. X}
  1520. X
  1521. X
  1522. Xshutdown_() {
  1523. X    FILE *to;
  1524. X    if ((to = fopen (prime_file, "a")) != NULL) {
  1525. X        fputs ("\07", to);  fflush (to);  fclose(to);
  1526. X    }
  1527. X}
  1528. X
  1529. Xabortit (message, status)
  1530. Xchar *message;
  1531. Xint status;
  1532. X{
  1533. X    if(pred_on_display)
  1534. X    erase_pred_buffer(&editor_data);
  1535. X    shutdown_pty_and_tty();
  1536. X    shutdown_();
  1537. X    fprintf (stderr, "%s", message);
  1538. X    fflush (stdout); fflush (stderr);
  1539. X    exit (status);
  1540. X}
  1541. END_OF_FILE
  1542. if test 3279 -ne `wc -c <'rk_file.c'`; then
  1543.     echo shar: \"'rk_file.c'\" unpacked with wrong size!
  1544. fi
  1545. # end of 'rk_file.c'
  1546. fi
  1547. echo shar: End of archive 1 \(of 4\).
  1548. cp /dev/null ark1isdone
  1549. MISSING=""
  1550. for I in 1 2 3 4 ; do
  1551.     if test ! -f ark${I}isdone ; then
  1552.     MISSING="${MISSING} ${I}"
  1553.     fi
  1554. done
  1555. if test "${MISSING}" = "" ; then
  1556.     echo You have unpacked all 4 archives.
  1557.     rm -f ark[1-9]isdone
  1558. else
  1559.     echo You still need to unpack the following archives:
  1560.     echo "        " ${MISSING}
  1561. fi
  1562. ##  End of shell archive.
  1563. exit 0
  1564.  
  1565.